/*
 *  BlobDetectionSDL.cpp
 *  portVideoBlobDetection
 *
 *  Created by Pawel 'solydzajs' Solyga on 7/25/07.
 *  Copyright 2007 __MyCompanyName__. All rights reserved.
 *
 */

#include "BlobDetectionSDL.h"
#include "Tools.h"

BlobDetectionSDL::BlobDetectionSDL(SDL_Surface *frame): bd(frame->w, frame->h, frame->format->BytesPerPixel)
{
	image = frame;
	edgeColor = SDL_MapRGB(image->format, 0xff, 0x00, 0x00);
	rectColor = SDL_MapRGB(image->format, 0x00, 0xff, 0x00);
	numberFontColor = SDL_MapRGB(image->format, 0x00, 0x00, 0xff);
	
	imageData = new int[image->w * image->h];
	threshold = 0.50f;
	dimMinX = 5;
	dimMinY = 5;
	
	isDrawBlobs = true;
	isDrawBlobNumber = false;
	isDrawBlobEdges = true;
	isDrawBlobRect = true;
	gotSurface = true;
	
	sfont = SFont_InitDefaultFont();
	fontHeight = SFont_TextHeight(sfont);
	
	bd.setPosDiscrimination(false);
	bd.setThreshold(threshold);
	bd.setBlobDimensionMin(dimMinX, dimMinY);
	b.setParent(&bd);
	
}

BlobDetectionSDL::~BlobDetectionSDL()
{
	delete [] imageData;
	SFont_FreeFont(sfont);
}

void BlobDetectionSDL::drawBlobRectangle(float x1, float y1, float x2, float y2)
{
	SDL_Rectangle( image, x1*image->w , y1*image->h, x2*image->w, y2*image->h, rectColor);
}

void BlobDetectionSDL::drawBlobEdges(blobDetection::Blob &blob)
{
	for (int m=0;m<blob.getEdgeNb();m++)
	{
		eA = blob.getEdgeVertexA(m);
		eB = blob.getEdgeVertexB(m);
		if (eA.isOk() && eB.isOk())
			SDL_Line( image, eA.x*image->w, eA.y*image->h, eB.x*image->w, eB.y*image->h, edgeColor );
	}
}

void BlobDetectionSDL::drawBlobNumber(int number, float x, float y)
{
	std::string blobId = toString<int> (number); 
	if(sfont) 
		SFont_Write(image, sfont, x*image->w, y*image->h, blobId.c_str());
}

void BlobDetectionSDL::convertFrame()
{
	int x,y;
	unsigned char *data = (unsigned char *)image->pixels;

	for( y = 0; y < image->h; y++, data += image->w * image->format->BytesPerPixel )
		for( x = 0; x < image->w * image->format->BytesPerPixel; x += image->format->BytesPerPixel )
		{
			unsigned char r = data[x],g,b;
			
			int rint = r, gint, bint;
			rint = (rint & 0x000000FF);
				
			if( image->format->BytesPerPixel == 3)
			{
				g = data[x+1];
				b = data[x+2];
				
				gint = g;
				gint = (gint & 0x000000FF) << 8;
		
				bint = b;
				bint = (bint & 0x000000FF) << 16;
				imageData[x/image->format->BytesPerPixel +y*image->w] = rint | gint | bint;
			}
			else
			{
				imageData[x/image->format->BytesPerPixel +y*image->w] = rint;
			}
		}
}

void BlobDetectionSDL::setImage(SDL_Surface *newImage)
{
	gotSurface = true;
	image = newImage;
}

void BlobDetectionSDL::setThreshold(float threshold)
{
	this->threshold = threshold;
	bd.setThreshold(this->threshold);
}

void BlobDetectionSDL::setBlobDimensionMin(int x,int y)
{
	dimMinX = x;
	dimMinY = y;
	bd.setBlobDimensionMin(dimMinX, dimMinY);
}

void BlobDetectionSDL::setBlobRectangleColor(Uint8 r, Uint8 g, Uint8 b)
{
	this->rectColor = SDL_MapRGB(image->format, r, g, b);
}

void BlobDetectionSDL::setBlobEdgesColor(Uint8 r, Uint8 g, Uint8 b)
{
	this->edgeColor = SDL_MapRGB(image->format, r, g, b);
}

void BlobDetectionSDL::setBlobNumberFontColor(Uint8 r, Uint8 g, Uint8 b)
{
	this->numberFontColor = SDL_MapRGB(image->format, r, g, b);
}

void BlobDetectionSDL::setDrawBlobs(bool drawBlobs)
{
	isDrawBlobs = drawBlobs;
}

void BlobDetectionSDL::findBlobs()
{
	convertFrame();
	bd.computeBlobs(this->imageData);
}

void BlobDetectionSDL::process()
{
	findBlobs();
	drawBlobs();
}

blobDetection::BlobDetection* BlobDetectionSDL::getBlobDetectionAlgorithm()
{
	return &(this->bd);
}

void BlobDetectionSDL::drawBlobs()
{
	for (int n=0 ; n< bd.getBlobNb() ; n++)
	{
		b = bd.getBlob(n);
		if (b.isOk())
		{
			if( isDrawBlobRect)
			{
				drawBlobRectangle(b.xMin, b.yMin, b.xMax, b.yMax);
			}
			
			if( isDrawBlobEdges)
			{
				drawBlobEdges(b);
			}
			
			if( isDrawBlobNumber)
			{
				drawBlobNumber(b.id, b.x, b.y);
			}
		}
	}
}

void BlobDetectionSDL::setDrawBlobNumber(bool drawBlobNumber)
{
	isDrawBlobNumber = drawBlobNumber;
}

void BlobDetectionSDL::setDrawBlobEdges(bool drawBlobEdges)
{
	isDrawBlobEdges = drawBlobEdges;
}

void BlobDetectionSDL::setDrawBlobRect(bool drawBlobRect)
{
	isDrawBlobRect = drawBlobRect;
}
